home *** CD-ROM | disk | FTP | other *** search
/ EuroCD 3 / EuroCD 3.iso / Games / Doom / ADoom-0.8 / ADoom_src / amiga_video.c < prev    next >
C/C++ Source or Header  |  1998-06-24  |  44KB  |  1,327 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. #include <exec/exec.h>
  6. #include <dos/dos.h>
  7. #include <graphics/gfx.h>
  8. #include <graphics/gfxbase.h>
  9. #include <graphics/gfxmacros.h>
  10. #include <intuition/intuition.h>
  11. #include <libraries/asl.h>
  12. #include <libraries/lowlevel.h>
  13. #include <cybergraphics/cybergraphics.h>
  14. #include <devices/gameport.h>
  15. #include <devices/timer.h>
  16.  
  17. #include <proto/exec.h>
  18. #include <proto/dos.h>
  19. #include <proto/graphics.h>
  20. #include <proto/layers.h>
  21. #include <proto/intuition.h>
  22. #include <proto/asl.h>
  23. #include <proto/timer.h>
  24. #include <proto/lowlevel.h>
  25. #include <proto/cybergraphics.h>
  26.  
  27. #include "doomtype.h"
  28. #include "doomdef.h"
  29. #include "doomstat.h"
  30. #include "i_system.h"
  31. #include "i_video.h"
  32. #include "v_video.h"
  33. #include "m_argv.h"
  34. #include "d_main.h"
  35.  
  36. #include "amiga_median.h"
  37. #include "c2p_020.h"
  38. #include "c2p_030.h"
  39. #include "c2p_040.h"
  40. #include "c2p8_040_amlaukka.h"
  41. #include "mmu.h"
  42.  
  43. /*experimental_c2p_stuff***********************************************/
  44. extern int scaledviewwidth;
  45. void REGARGS (*c2p)(REG(a0, const UBYTE *chunky),
  46.                     REG(a1, UBYTE *raster),
  47.                     REG(a2, const UBYTE *chunky_end)) = NULL;
  48.  
  49. /**********************************************************************/
  50. extern struct ExecBase *SysBase;
  51. struct Library *AslBase = NULL;
  52. struct Library *CyberGfxBase = NULL;
  53. struct Library *LowLevelBase = NULL;
  54.  
  55. extern int cpu_type;
  56.  
  57. static struct ScreenModeRequester *video_smr = NULL;
  58. static struct Screen *video_screen = NULL;
  59. static struct Window *video_window = NULL;
  60. static struct BitMap video_bitmap[3] = {
  61.   {0, 0, 0, 0, 0, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}},
  62.   {0, 0, 0, 0, 0, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}},
  63.   {0, 0, 0, 0, 0, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}}
  64. };
  65. static PLANEPTR video_raster[3] = {NULL, NULL, NULL};    /* contiguous bitplanes */
  66. static UBYTE *video_compare_buffer[3] = {NULL, NULL, NULL};    /* in fastmem */
  67. static struct RastPort video_rastport[3];
  68. static struct ScreenBuffer *video_sb[2] = {NULL, NULL};
  69. static struct DBufInfo *video_db = NULL;
  70. static struct MsgPort *video_mp = NULL;
  71. static int video_which = 0;
  72. static BYTE video_sigbit1 = -1;
  73. static BYTE video_sigbit2 = -1;
  74. static volatile BYTE video_sigbit3 = -1;
  75. static struct Task *video_maintask;
  76. static struct Task *video_fliptask = NULL;
  77. static int video_depth = 0;
  78. static int video_oscan_height;
  79. static ULONG video_colourtable[1 + 3*256 + 1];
  80. static volatile WORD video_palette_changed = 0;
  81. static BOOL video_is_ehb_mode = FALSE;
  82. static BOOL video_is_native_mode = FALSE;
  83. static BOOL video_is_cyber_mode = FALSE;
  84. static BOOL video_is_using_blitter = FALSE;
  85. static BOOL video_blit_is_in_progress = FALSE;
  86. static BOOL video_use_mmu = FALSE;
  87. static BOOL video_is_directcgx = FALSE;
  88. static BOOL video_doing_fps = FALSE;
  89. static BOOL video_bitmap_is_locked = FALSE;
  90. static APTR video_bitmap_handle;
  91. static int video_f_cache_mode;
  92. static int video_c_cache_mode;
  93. static struct RastPort video_temprp;
  94. static struct BitMap video_tmp_bm = {
  95.   0, 0, 0, 0, 0, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
  96. };
  97. static UBYTE video_xlate[256];   /* xlate colour from 8-bit to 6-bit EHB */
  98. static UWORD __chip emptypointer[] = {
  99.   0x0000, 0x0000,    /* reserved, must be NULL */
  100.   0x0000, 0x0000,     /* 1 row of image data */
  101.   0x0000, 0x0000    /* reserved, must be NULL */
  102. };
  103.  
  104. /* gameport stuff */
  105. static struct MsgPort *gameport_mp = NULL;
  106. static struct IOStdReq *gameport_io = NULL;
  107. static BOOL gameport_is_open = FALSE;
  108. static BOOL gameport_io_in_progress = FALSE;
  109. static struct InputEvent gameport_ie;
  110. static BYTE gameport_ct;        /* controller type */
  111. struct GamePortTrigger gameport_gpt = {
  112.   GPTF_UPKEYS | GPTF_DOWNKEYS,    /* gpt_Keys */
  113.   0,                /* gpt_Timeout */
  114.   1,                /* gpt_XDelta */
  115.   1                /* gpt_YDelta */
  116. };
  117.  
  118. /****************************************************************************/
  119. struct Library *TimerBase = NULL;
  120. static struct MsgPort *timermp = NULL;
  121. static struct timerequest *timerio = NULL;
  122. static ULONG timerclosed = TRUE;
  123. static ULONG eclocks_per_second; /* EClock frequency in Hz */
  124.  
  125. static struct EClockVal start_time;
  126. static unsigned int blit_time = 0;
  127. static unsigned int safe_time = 0;
  128. static unsigned int c2p_time = 0;
  129. static unsigned int wpa8_time = 0;
  130. static unsigned int lock_time = 0;
  131. static unsigned int total_frames = 0;
  132.  
  133. /****************************************************************************/
  134. static __inline void start_timer (void)
  135. {
  136.   ReadEClock (&start_time);
  137. }
  138.  
  139. /****************************************************************************/
  140. static __inline unsigned int end_timer (void)
  141. {
  142.   struct EClockVal end_time;
  143.  
  144.   ReadEClock (&end_time);
  145.   return end_time.ev_lo - start_time.ev_lo;
  146. }
  147.  
  148. /****************************************************************************/
  149.  
  150. static char *mode_name (ULONG mode)
  151. /* Return a mode name for given mode, compatible with ASL mode requester */
  152. /* Use name in DisplayInfo database if available */
  153. /* else manually construct the name */
  154. {
  155.   APTR handle;
  156.   char *p;
  157.   struct NameInfo nameinfo;
  158.   struct DimensionInfo dimsinfo;
  159.   static char modename[DISPLAYNAMELEN + 4 + 4 + 11 + 1];
  160.  
  161.   p = modename;
  162.   *p = '\0';
  163.   if ((handle = FindDisplayInfo (mode & ~SPRITES)) != NULL) {
  164.     if (GetDisplayInfoData (handle, (UBYTE *)&nameinfo,
  165.                             sizeof(nameinfo), DTAG_NAME,
  166.                             NULL) > sizeof(struct QueryHeader)) {
  167.       p += sprintf (p, "%s", nameinfo.Name);
  168.     } else if (GetDisplayInfoData (handle, (UBYTE *)&dimsinfo,
  169.                                    sizeof(dimsinfo), DTAG_DIMS,
  170.                                    NULL) >= 66 /* sizeof(dimsinfo)*/) {
  171.       switch (mode & MONITOR_ID_MASK) {
  172.         case DEFAULT_MONITOR_ID:
  173.           p += sprintf (p, "DEFAULT:");      /* PAL or NTSC??? */
  174.           break;
  175.         case NTSC_MONITOR_ID:
  176.           p += sprintf (p, "NTSC:");
  177.           break;
  178.         case PAL_MONITOR_ID:
  179.           p += sprintf (p, "PAL:");
  180.           break;
  181.         case VGA_MONITOR_ID:
  182.           p += sprintf (p, "MULTISCAN:");
  183.           break;
  184.         case A2024_MONITOR_ID:
  185.           p += sprintf (p, "A2024:");
  186.           break;
  187.         case PROTO_MONITOR_ID:
  188.           p += sprintf (p, "PROTO:");
  189.           break;
  190.         case EURO72_MONITOR_ID:
  191.           p += sprintf (p, "EURO72:");
  192.           break;
  193.         case EURO36_MONITOR_ID:
  194.           p += sprintf (p, "EURO36:");
  195.           break;
  196.         case SUPER72_MONITOR_ID:
  197.           p += sprintf (p, "SUPER72:");
  198.           break;
  199.         case DBLNTSC_MONITOR_ID:
  200.           p += sprintf (p, "DBLNTSC:");
  201.           break;
  202.         case DBLPAL_MONITOR_ID:
  203.           p += sprintf (p, "DBLPAL:");
  204.           break;
  205.         default:
  206.           p += sprintf (p, "(unknown):");
  207.           break;
  208.       }
  209.       p += sprintf (p, "%d x %d",
  210.                     dimsinfo.Nominal.MaxX - dimsinfo.Nominal.MinX + 1,
  211.                     dimsinfo.Nominal.MaxY - dimsinfo.Nominal.MinY + 1);
  212.       if ((mode & HAM_KEY) != 0)
  213.         p += sprintf (p, " HAM");
  214.       if ((mode & EXTRAHALFBRITE_KEY) != 0)
  215.         p += sprintf (p, " EHB");
  216.       if ((mode & LACE) != 0)
  217.         p += sprintf (p, " Interlaced");
  218.     } else {
  219.       p += sprintf (p, "%s", "(unnamed)");
  220.       if ((mode & HAM_KEY) != 0)
  221.         p += sprintf (p, " HAM");
  222.       if ((mode & EXTRAHALFBRITE_KEY) != 0)
  223.         p += sprintf (p, " EHB");
  224.       if ((mode & LACE) != 0)
  225.         p += sprintf (p, " Interlaced");
  226.     }
  227.   } else {
  228.     p += sprintf (p, "%s", "(unavailable)");
  229.   }
  230.   return (modename);
  231. }
  232.  
  233. /****************************************************************************/
  234.  
  235. static ULONG parse_mode (char *modename)
  236. /* Modename may be descriptive name ("PAL Lores"), or hex ("$00420001" or */
  237. /* "0x12345678") or decimal ("32768"). */
  238. {
  239.   ULONG mode, reason;
  240.  
  241.   mode = INVALID_ID;
  242.   if (modename != NULL) {
  243.     if (modename[0] == '0' && modename[1] == 'x') {
  244.       if (sscanf (&modename[2], "%lx", &mode) != 1)
  245.         mode = INVALID_ID;
  246.     } else if (modename[0] == '$') {
  247.       if (sscanf (&modename[1], "%lx", &mode) != 1)
  248.         mode = INVALID_ID;
  249.     } else if (modename[0] >= '0' && modename[0] <= '9') {
  250.       if (sscanf (modename, "%ld", &mode) != 1)
  251.         mode = INVALID_ID;
  252.     } else {
  253.       while ((mode = NextDisplayInfo (mode)) != INVALID_ID) {
  254.         if ((mode & LORESDPF_KEY) == 0) {
  255.           /* printf ("$%08x  \"%s\"\n", mode, mode_name (mode)); */
  256.           if (strcmp (mode_name (mode), modename) == 0)
  257.             break;
  258.         }
  259.       }
  260.     }
  261.   }
  262.   if (FindDisplayInfo (mode) == NULL)
  263.     I_Error ("ScreenMode not in database: \"%s\"", modename);
  264.   if ((reason = ModeNotAvailable (mode)) != 0)
  265.     I_Error ("Mode $%08x is not available: %ld", mode, reason);
  266.   return (mode);
  267. }
  268.  
  269. /**********************************************************************/
  270. static void video_do_fps (struct RastPort *rp)
  271. {
  272.   ULONG x;
  273.   static struct EClockVal start_time = {0, 0};
  274.   struct EClockVal end_time;
  275.   char msg[4];
  276.  
  277.   ReadEClock (&end_time);
  278.   x = end_time.ev_lo - start_time.ev_lo;
  279.   if (x != 0) {
  280.     x = (eclocks_per_second + (x >> 1)) / x;   /* round to nearest */
  281.     msg[0] = (x % 1000) / 100 + '0';
  282.     msg[1] = (x % 100) / 10 + '0';
  283.     msg[2] = (x % 10) + '0';
  284.     msg[3] = '\0';
  285.     Move (rp, 0, 6);
  286.     Text (rp, msg, 3);
  287.   }
  288.   start_time = end_time;
  289. }
  290.  
  291. /**********************************************************************/
  292. // This asynchronous task waits in a loop for sigbit3 signals.
  293. // Sigbit3 is signalled when the next frame is just finished.
  294. // Sigbit3 may be signalled from the qblit() cleanup function or from the
  295. // main task.
  296. // On receipt of sigbit3, we load the new palette and call ChangeScreenBuffer().
  297. // This way there is no delay calling ChangeScreenBuffer() after the last blit
  298. // has finished.
  299. // The main 3D rendering task may be interrupted to call ChangeScreenBuffer()
  300. // SIGBREAKF_CTRL_F and SIGBREAKF_CTRL_C are used for synchronisation
  301. // with the main task.
  302.  
  303. static void __saveds __interrupt video_flipscreentask (void)
  304. {
  305.   ULONG sig;
  306.   struct MsgPort *video_dispport, *video_safeport;
  307.   BOOL going, video_disp, video_safe;
  308.   int i;
  309.  
  310.   video_sigbit3 = AllocSignal(-1);
  311.   Signal (video_maintask, SIGBREAKF_CTRL_F);
  312.   video_dispport = CreatePort (NULL, 0);
  313.   video_safeport = CreatePort (NULL, 0);
  314.   video_disp = TRUE;
  315.   video_safe = TRUE;
  316.   for (i = 0; i < 2; i++) {
  317.     video_sb[i]->sb_DBufInfo->dbi_DispMessage.mn_ReplyPort = video_dispport;
  318.     video_sb[i]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = video_safeport;
  319.   }
  320.   going = (video_sigbit3 != -1) &&
  321.           (video_dispport != NULL) &&
  322.           (video_safeport != NULL);
  323.   while (going) {
  324.     sig = Wait (1 << video_sigbit3 | SIGBREAKF_CTRL_C);
  325.     if ((sig & (1 << video_sigbit3)) != 0) {
  326.       if (video_doing_fps)
  327.         video_do_fps (&video_rastport[video_which]);
  328.       LoadRGB32 (&video_screen->ViewPort, video_colourtable);
  329.       if ((ChangeScreenBuffer (video_screen, video_sb[video_which])) != 0) {
  330.         video_disp = FALSE;
  331.         video_safe = FALSE;
  332.       }
  333.       if (!video_safe) {  /* wait until safe */
  334.         Wait (1 << video_safeport->mp_SigBit);
  335.         while (GetMsg (video_safeport) != NULL) /* clear message queue */
  336.           /* do nothing */ ;
  337.         video_safe = TRUE;
  338.       }
  339.       Signal (video_maintask, SIGBREAKF_CTRL_F);
  340.       if (!video_disp) {  /* wait for previous frame to be displayed */
  341.         Wait (1 << video_dispport->mp_SigBit);
  342.         while (GetMsg (video_dispport) != NULL) /* clear message queue */
  343.           /* do nothing */ ;
  344.         video_disp = TRUE;
  345.       }
  346.     }
  347.     if ((sig & SIGBREAKF_CTRL_C) != 0) {
  348.       going = FALSE;
  349.     }
  350.   }
  351.   if (!video_safe) {  /* wait for safe */
  352.     Wait (1 << video_safeport->mp_SigBit);
  353.     while (GetMsg (video_safeport) != NULL) /* clear message queue */
  354.       /* do nothing */ ;
  355.     video_safe = TRUE;
  356.   }
  357.   if (!video_disp) {  /* wait for last frame to be displayed */
  358.     Wait (1 << video_dispport->mp_SigBit);
  359.     while (GetMsg (video_dispport) != NULL) /* clear message queue */
  360.       /* do nothing */ ;
  361.     video_disp = TRUE;
  362.   }
  363.   if (video_sigbit3 != -1)
  364.     FreeSignal (video_sigbit3);
  365.   if (video_dispport != NULL)
  366.     DeletePort (video_dispport);
  367.   if (video_safeport != NULL)
  368.     DeletePort (video_safeport);
  369.   Signal (video_maintask, SIGBREAKF_CTRL_F);
  370.   Wait (0);
  371. }
  372.  
  373. /**********************************************************************/
  374. // Called by D_DoomMain,
  375. // determines the hardware configuration
  376. // and sets up the video mode
  377. void I_InitGraphics (void)
  378. {
  379.   int i;
  380.   ULONG propertymask, idcmp, wflags, width, pixfmt;
  381.   struct Rectangle rect;
  382.   char reqtitle[32];
  383.   int mode, depth, nbytes, p;
  384.   DisplayInfoHandle handle;
  385.   struct DisplayInfo dispinfo;
  386.   struct DimensionInfo dimsinfo;
  387.  
  388.   video_maintask = FindTask(NULL);
  389.  
  390.   if (AslBase == NULL) {
  391.     if ((AslBase = OpenLibrary ("asl.library", 37L)) == NULL ||
  392.         (video_smr = AllocAslRequestTags (ASL_ScreenModeRequest, TAG_DONE)) == NULL) {
  393.       I_Error ("OpenLibrary(""asl.library"", 37) failed");
  394.     }
  395.   }
  396.  
  397.   if ((timermp = CreatePort (NULL, 0)) == NULL)
  398.     I_Error ("Can't create messageport!");
  399.   if ((timerio = (struct timerequest *)CreateExtIO (timermp,
  400.                   sizeof(struct timerequest))) == NULL)
  401.     I_Error ("Can't create External IO!");
  402.   if (timerclosed = OpenDevice (TIMERNAME, UNIT_ECLOCK,
  403.                                 (struct IORequest *)timerio, 0))
  404.     I_Error ("Can't open timer.device!");
  405.   TimerBase = (struct Library *)timerio->tr_node.io_Device;
  406.   eclocks_per_second = ReadEClock (&start_time);
  407.  
  408.   video_doing_fps = M_CheckParm ("-fps");
  409.  
  410.   /* first check tooltypes for SCREENMODE */
  411.   mode = -1;
  412.   p = M_CheckParm ("-screenmode");
  413.   if (p && p < myargc - 1) {
  414.     mode = parse_mode (myargv[p+1]);
  415.   }
  416.  
  417.   /* if not found in icon tooltypes, then put up a ScreenMode requester */
  418.   if (mode == -1) {
  419.     propertymask = /* DIPF_IS_EXTRAHALFBRITE | */ DIPF_IS_DUALPF |
  420.                    DIPF_IS_PF2PRI | DIPF_IS_HAM;
  421.     if (GfxBase->LibNode.lib_Version >= 39)
  422.       mode = BestModeID (BIDTAG_NominalWidth,     SCREENWIDTH,
  423.                          BIDTAG_NominalHeight,    SCREENHEIGHT,
  424.                          BIDTAG_Depth,            video_depth,
  425.                          BIDTAG_DIPFMustNotHave,  propertymask,
  426.                          TAG_DONE);
  427.     else
  428.       mode = EXTRAHALFBRITE_KEY;
  429.     if (AslBase->lib_Version >= 38) {
  430.       sprintf (reqtitle, "ADoom %dx%d", SCREENWIDTH, SCREENHEIGHT);
  431.       if (!AslRequestTags (video_smr,
  432.                            ASLSM_TitleText,        (ULONG)reqtitle,
  433.                            ASLSM_InitialDisplayID, mode,
  434.                            ASLSM_MinWidth,         SCREENWIDTH,
  435.                            ASLSM_MinHeight,        SCREENHEIGHT,
  436.                            ASLSM_MinDepth,         6,
  437.                            ASLSM_MaxDepth,         8,
  438.                            ASLSM_PropertyMask,     propertymask,
  439.                            ASLSM_PropertyFlags,    0,
  440.                            TAG_DONE)) {
  441.         I_Error ("AslRequest() failed");
  442.       }
  443.       mode = video_smr->sm_DisplayID;
  444.     }
  445.   }
  446.  
  447.   if ((handle = FindDisplayInfo (mode)) == NULL) {
  448.     I_Error ("Can't FindDisplayInfo() for mode %08x", mode);
  449.   }
  450.   if ((nbytes = GetDisplayInfoData (handle, (UBYTE *)&dispinfo,
  451.                                     sizeof(struct DisplayInfo), DTAG_DISP,
  452.                                     NULL)) < 40 /*sizeof(struct DisplayInfo)*/) {
  453.     I_Error ("Can't GetDisplayInfoData() for mode %08x, got %d bytes",
  454.              mode, nbytes);
  455.   }
  456.   if ((nbytes = GetDisplayInfoData (handle, (UBYTE *)&dimsinfo,
  457.                                     sizeof(dimsinfo), DTAG_DIMS,
  458.                                     NULL)) < 66 /* sizeof(dimsinfo)*/) {
  459.     I_Error ("Can't GetDisplayInfoData() for mode %08x, got %d bytes",
  460.              mode, nbytes);
  461.   }
  462.  
  463.   video_oscan_height = dimsinfo.MaxOScan.MaxY - dimsinfo.MaxOScan.MinY + 1;
  464.  
  465.   video_is_cyber_mode = 0;
  466.   if ((CyberGfxBase = OpenLibrary ("cybergraphics.library", 0)) != NULL) {
  467.     video_is_cyber_mode = IsCyberModeID (mode);
  468.   }
  469.  
  470.   /* this test needs improving */
  471.   video_is_native_mode = ((GfxBase->LibNode.lib_Version < 39 ||
  472.                            (dispinfo.PropertyFlags & DIPF_IS_EXTRAHALFBRITE) != 0 ||
  473.                            (dispinfo.PropertyFlags & DIPF_IS_AA) != 0 ||
  474.                            (dispinfo.PropertyFlags & DIPF_IS_ECS) != 0 ||
  475.                            (dispinfo.PropertyFlags & DIPF_IS_DBUFFER) != 0) &&
  476.                           !video_is_cyber_mode &&
  477.                           (dispinfo.PropertyFlags & DIPF_IS_FOREIGN) == 0);
  478.  
  479.   video_is_ehb_mode = ((dispinfo.PropertyFlags & DIPF_IS_EXTRAHALFBRITE) != 0);
  480.  
  481.   printf ("Screen Mode $%08x is ", mode);
  482.   if (video_is_native_mode)
  483.     printf (" NATIVE-PLANAR");
  484.   else
  485.     printf (" FOREIGN");
  486.   if (video_is_ehb_mode)
  487.     printf (" EXTRAHALFBRITE");
  488.   else
  489.     printf (" 8-BIT");
  490.   if (video_is_cyber_mode)
  491.     printf (" CYBERGRAPHX");
  492.   printf ("\n");
  493.  
  494.   if (video_is_ehb_mode)
  495.     video_depth = 6;
  496.   else
  497.     video_depth = 8;
  498.  
  499.   rect.MinX = 0;
  500.   rect.MinY = 0;
  501.   rect.MaxX = SCREENWIDTH - 1;
  502.   rect.MaxY = SCREENHEIGHT - 1;
  503.  
  504.   if (M_CheckParm ("-mmu") && cpu_type >= 68040)
  505.        video_use_mmu = true;
  506.  
  507.   if (video_is_native_mode) {
  508.     video_is_using_blitter = (cpu_type < 68040);
  509.  
  510.     for (i = 0; i < (video_is_using_blitter ? 2 : 3); i++) {
  511.       /* use the mmu hack only if cpu is 68040+ and user specified -mmu */
  512.       if (video_use_mmu) {
  513.         ULONG *ptr, mem;
  514.         mem = (ULONG)AllocVec (SCREENWIDTH * SCREENHEIGHT / 8 * video_depth +
  515.                                4100, MEMF_CHIP);
  516.         if (!mem)
  517.           I_Error ("AllocVec() failed");
  518.         ptr = (ULONG*)((mem & ~0xfff) + 4096);
  519.     ptr[-1] = 4096 - (mem & 0xfff);
  520.     video_raster[i] = (byte *)ptr;
  521.         video_c_cache_mode = mmu_mark (video_raster[i],
  522.                                    SCREENWIDTH * SCREENHEIGHT / 8 * video_depth,
  523.                                    CM_IMPRECISE, SysBase);
  524.       } else {
  525.         if ((video_raster[i] = (PLANEPTR)AllocRaster (SCREENWIDTH,
  526.                                            video_depth * SCREENHEIGHT)) == NULL)
  527.           I_Error ("AllocRaster() failed");
  528.       }
  529.       memset (video_raster[i], 0, video_depth * RASSIZE (SCREENWIDTH, SCREENHEIGHT));
  530.       InitBitMap (&video_bitmap[i], video_depth, SCREENWIDTH, SCREENHEIGHT);
  531.       for (depth = 0; depth < video_depth; depth++)
  532.         video_bitmap[i].Planes[depth] = video_raster[i] +
  533.                                     depth * RASSIZE (SCREENWIDTH, SCREENHEIGHT);
  534.       InitRastPort (&video_rastport[i]);
  535.       video_rastport[i].BitMap = &video_bitmap[i];
  536.       SetAPen (&video_rastport[i], (1 << video_depth) - 1);
  537.       SetBPen (&video_rastport[i], 0);
  538.       SetDrMd (&video_rastport[i], JAM2);
  539.     }
  540.  
  541.     /* experimental c2p stuff */
  542.     if (!video_is_using_blitter)
  543.       c2p = c2p8_reloc (screens[0], &video_bitmap[0], SysBase);
  544.  
  545.     if ((video_screen = OpenScreenTags (NULL,
  546.           SA_Type,        CUSTOMSCREEN | CUSTOMBITMAP,
  547.           SA_DisplayID,   mode,
  548.           SA_DClip,       (ULONG)&rect,
  549.           SA_Width,       SCREENWIDTH,
  550.           SA_Height,      SCREENHEIGHT,
  551.           SA_Depth,       video_depth,
  552.           /* SA_Draggable,FALSE, */
  553.           /* SA_AutoScroll,FALSE, */
  554.           /* SA_Exclusive,TRUE, */
  555.           SA_Quiet,       TRUE,
  556.           SA_BitMap,      &video_bitmap[0], /* custom bitmap, contiguous planes */
  557.           TAG_DONE)) == NULL) {
  558.       I_Error ("OpenScreen() failed");
  559.     }
  560.     for (i = 0; i < (video_is_using_blitter ? 2 : 3); i++) {
  561.       if ((video_compare_buffer[i] = malloc (SCREENWIDTH * SCREENHEIGHT)) == NULL)
  562.         I_Error ("Out of memory allocating %d bytes", SCREENWIDTH * SCREENHEIGHT);
  563.       memset (video_compare_buffer[i], 0, SCREENWIDTH * SCREENHEIGHT);
  564.     }
  565.     if (video_is_using_blitter) {
  566.       for (i = 0; i < 2; i++) {
  567.     if ((video_sb[i] = AllocScreenBuffer (video_screen, &video_bitmap[i], 0)) == NULL)
  568.       I_Error ("Can't allocate structure for double buffering");
  569.       }
  570.     } else {
  571.       video_db = AllocDBufInfo (&video_screen->ViewPort);
  572.       video_mp = CreateMsgPort ();
  573.       if (!video_db || !video_mp)
  574.         I_Error ("Can't allocate dbuffer information");
  575.       video_db->dbi_DispMessage.mn_ReplyPort = video_mp;
  576.       video_which = 1;
  577.       ChangeVPBitMap (&video_screen->ViewPort, &video_bitmap[0], video_db);
  578.     }
  579.   } else {  /* non-native ScreenMode */
  580.     if (video_is_cyber_mode && M_CheckParm ("-directcgx"))
  581.       video_is_directcgx = TRUE;
  582.     if ((video_screen = OpenScreenTags (NULL,
  583.           SA_Type,        CUSTOMSCREEN,
  584.           SA_DisplayID,   mode,
  585.           SA_DClip,       (ULONG)&rect,
  586.           SA_Width,       SCREENWIDTH,
  587.           SA_Height,      video_is_directcgx ? video_oscan_height << 1 : SCREENHEIGHT,
  588.           SA_Depth,       video_depth,
  589.           /* SA_Draggable,FALSE, */
  590.           /* SA_AutoScroll,FALSE, */
  591.           /* SA_Exclusive,TRUE, */
  592.           SA_Quiet,       TRUE,
  593.           TAG_DONE)) == NULL) {
  594.       I_Error ("OpenScreen() failed");
  595.     }
  596.   }
  597.  
  598.   if (video_is_directcgx) {
  599.     video_bitmap_handle = LockBitMapTags (video_screen->ViewPort.RasInfo->BitMap,
  600.                                           LBMI_WIDTH,       &width,
  601.                                           LBMI_DEPTH,       &depth,
  602.                                           LBMI_PIXFMT,      &pixfmt,
  603.                                           LBMI_BASEADDRESS, &screens[0],
  604.                                           TAG_DONE);
  605.     UnLockBitMap (video_bitmap_handle);
  606.     if (/* width != SCREENWIDTH || */
  607.         depth != video_depth ||
  608.         pixfmt != PIXFMT_LUT8) {
  609.       I_Error ("ScreenMode of width %d, depth %d, pixfmt %d cannot be used with -directcgx",
  610.                width, depth, pixfmt);
  611.     }
  612.   } else {
  613.     if (video_use_mmu) {
  614.       video_f_cache_mode = mmu_mark (screens[0],
  615.                                      (SCREENWIDTH * SCREENHEIGHT + 4096) & ~0xfff,
  616.                                      CM_WRITETHROUGH, SysBase);
  617.     }
  618.   }
  619.  
  620.   idcmp = IDCMP_RAWKEY;
  621.   wflags = WFLG_ACTIVATE | WFLG_BORDERLESS | WFLG_RMBTRAP;
  622.   if (M_CheckParm("-mouse") != NULL) {
  623.     idcmp |= IDCMP_MOUSEMOVE | IDCMP_DELTAMOVE | IDCMP_MOUSEBUTTONS;
  624.     wflags |= WFLG_REPORTMOUSE;
  625.   }
  626.  
  627.   if ((video_window = OpenWindowTags (NULL,
  628.         WA_Left,         0,
  629.         WA_Top,          0,
  630.         WA_Width,        SCREENWIDTH,
  631.         WA_Height,       SCREENHEIGHT,
  632.         WA_IDCMP,        idcmp,
  633.         WA_Flags,        wflags,
  634.         WA_CustomScreen, video_screen,
  635.         TAG_DONE)) == NULL) {
  636.     I_Error ("OpenWindow() failed");
  637.   }
  638.  
  639.   InitBitMap (&video_tmp_bm, video_depth, SCREENWIDTH, 1);
  640.   for (depth = 0; depth < video_depth; depth++)
  641.     if ((video_tmp_bm.Planes[depth] = (PLANEPTR)AllocRaster (SCREENWIDTH, 1)) == NULL)
  642.       I_Error ("AllocRaster() failed");
  643.   video_temprp = *video_window->RPort;
  644.   video_temprp.Layer = NULL;
  645.   video_temprp.BitMap = &video_tmp_bm;
  646.  
  647.   SetPointer (video_window, emptypointer, 1, 16, 0, 0);
  648.  
  649.   if (video_is_native_mode) {
  650.     if (video_is_using_blitter) {
  651.       if ((video_sigbit1 = AllocSignal(-1)) == -1 ||
  652.       (video_sigbit2 = AllocSignal(-1)) == -1)
  653.     I_Error ("Can't allocate signal!\n");
  654.       Signal (video_maintask, (1 << video_sigbit1) | (1 << video_sigbit2));
  655.                                                 /* initial state is finished */
  656.       if ((video_fliptask = CreateTask ("ADoom_flipscreen", 5,
  657.                     video_flipscreentask, 4096)) == NULL)
  658.     I_Error ("Can't create subtask");
  659.       Wait (SIGBREAKF_CTRL_F);
  660.       if (video_sigbit3 == -1)
  661.     I_Error ("Subtask couldn't allocate sigbit");
  662.       if (!video_is_ehb_mode)
  663.         c2p1x1_cpu3blit1_queue_init (SCREENWIDTH, SCREENHEIGHT, 0,
  664.                                      SCREENWIDTH * SCREENHEIGHT / 8,
  665.                                      1 << video_sigbit1, 1 << video_sigbit3,
  666.                                      video_maintask, video_fliptask);
  667.     }
  668.   }
  669.  
  670.   /* joystick initialisation */
  671.  
  672.   if (M_CheckParm ("-joypad") != NULL) {
  673.  
  674.     if ((LowLevelBase = OpenLibrary ("lowlevel.library", 0)) == NULL)
  675.       I_Error ("-joypad option specified and can't open lowlevel.library");
  676.  
  677.   } else {
  678.  
  679.     if ((gameport_mp = CreatePort (NULL, 0)) == NULL ||
  680.         (gameport_io = (struct IOStdReq *)CreateExtIO (gameport_mp,
  681.                                               sizeof(struct IOStdReq))) == NULL ||
  682.         OpenDevice ("gameport.device", 1, (struct IORequest *)gameport_io, 0) != 0)
  683.       I_Error ("Can't open gameport.device");
  684.  
  685.     gameport_is_open = TRUE;
  686.  
  687.     Forbid ();
  688.  
  689.     gameport_io->io_Command = GPD_ASKCTYPE;
  690.     gameport_io->io_Length = 1;
  691.     gameport_io->io_Data = &gameport_ct;
  692.     DoIO ((struct IORequest *)gameport_io);
  693.  
  694.     if (gameport_ct != GPCT_NOCONTROLLER) {
  695.  
  696.       Permit ();
  697.       fprintf (stderr, "Another task is using the gameport!  Joystick disabled");
  698.       CloseDevice ((struct IORequest *)gameport_io);
  699.       gameport_is_open = FALSE;
  700.  
  701.     } else {
  702.  
  703.       gameport_ct = GPCT_ABSJOYSTICK;
  704.       gameport_io->io_Command = GPD_SETCTYPE;
  705.       gameport_io->io_Length = 1;
  706.       gameport_io->io_Data = &gameport_ct;
  707.       DoIO ((struct IORequest *)gameport_io);
  708.  
  709.       Permit ();
  710.  
  711.       gameport_io->io_Command = GPD_SETTRIGGER;
  712.       gameport_io->io_Length = sizeof(struct GamePortTrigger);
  713.       gameport_io->io_Data = &gameport_gpt;
  714.       DoIO ((struct IORequest *)gameport_io);
  715.  
  716.       gameport_io->io_Command = GPD_READEVENT;
  717.       gameport_io->io_Length = sizeof (struct InputEvent);
  718.       gameport_io->io_Data = &gameport_ie;
  719.       SendIO ((struct IORequest *)gameport_io);
  720.       gameport_io_in_progress = TRUE;
  721.     }
  722.   }
  723. }
  724.  
  725. /**********************************************************************/
  726. void I_ShutdownGraphics (void)
  727. {
  728.   int depth, i;
  729.  
  730.   if (video_is_directcgx && video_bitmap_is_locked) {
  731.     UnLockBitMap (video_bitmap_handle);
  732.     video_bitmap_is_locked = FALSE;
  733.   }
  734.   if (LowLevelBase != NULL) {
  735.     CloseLibrary (LowLevelBase);
  736.     LowLevelBase = NULL;
  737.   }
  738.   if (gameport_io_in_progress) {
  739.     AbortIO ((struct IORequest *)gameport_io);
  740.     WaitIO ((struct IORequest *)gameport_io);
  741.     gameport_io_in_progress = FALSE;
  742.     gameport_ct = GPCT_NOCONTROLLER;
  743.     gameport_io->io_Command = GPD_SETCTYPE;
  744.     gameport_io->io_Length = 1;
  745.     gameport_io->io_Data = &gameport_ct;
  746.     DoIO ((struct IORequest *)gameport_io);
  747.   }
  748.   if (gameport_is_open) {
  749.     CloseDevice ((struct IORequest *)gameport_io);
  750.     gameport_is_open = FALSE;
  751.   }
  752.   if (gameport_io != NULL) {
  753.     DeleteExtIO ((struct IORequest *)gameport_io);
  754.     gameport_io = NULL;
  755.   }
  756.   if (gameport_mp != NULL) {
  757.     DeletePort (gameport_mp);
  758.     gameport_mp = NULL;
  759.   }
  760.   if (video_blit_is_in_progress) {
  761.     Wait (SIGBREAKF_CTRL_F);
  762.     video_blit_is_in_progress = FALSE;
  763.   }
  764.   if (video_fliptask != NULL) {
  765.     Signal (video_fliptask, SIGBREAKF_CTRL_C);
  766.     Wait (SIGBREAKF_CTRL_F);
  767.     DeleteTask (video_fliptask);
  768.     video_fliptask = NULL;
  769.   }
  770.   if (video_is_using_blitter) {
  771.     if (video_sigbit1 != -1) {
  772.       Wait (1 << video_sigbit1);  // wait for last c2p8 to finish pass 3
  773.     FreeSignal (video_sigbit1);
  774.       video_sigbit1 = -1;
  775.     }
  776.     if (video_sigbit2 != -1) {
  777.       Wait (1 << video_sigbit2);  // wait for last c2p8 to completely finish
  778.     FreeSignal (video_sigbit2);
  779.       video_sigbit2 = -1;
  780.     }
  781.   }
  782.   if (video_window != NULL) {
  783.     ClearPointer (video_window);
  784.     CloseWindow (video_window);
  785.     video_window = NULL;
  786.   }
  787.   if (video_is_using_blitter) {
  788.     for (i = 0; i < 2; i++) {
  789.       if (video_sb[i] != NULL) {
  790.     FreeScreenBuffer (video_screen, video_sb[i]);
  791.     video_sb[i] = NULL;
  792.       }
  793.     }
  794.   } else {
  795.     if (video_mp) {
  796.       WaitPort (video_mp);
  797.       while (GetMsg(video_mp));
  798.       DeleteMsgPort (video_mp);
  799.       video_mp = NULL; 
  800.     }
  801.     if (video_db) {
  802.       FreeDBufInfo (video_db);
  803.       video_db = NULL;
  804.     }
  805.   }
  806.   if (video_screen != NULL) {
  807.     CloseScreen (video_screen);
  808.     video_screen = NULL;
  809.   }
  810.   for (depth = 0; depth < video_depth; depth++) {
  811.     if (video_tmp_bm.Planes[depth] != NULL) {
  812.       FreeRaster (video_tmp_bm.Planes[depth], SCREENWIDTH, 1);
  813.       video_tmp_bm.Planes[depth] = NULL;
  814.     }
  815.   }
  816.   for (i = 0; i < (video_is_using_blitter ? 2 : 3); i++) {
  817.     if (video_raster[i] != NULL) {
  818.       if (video_use_mmu) {
  819.         ULONG *ptr = (ULONG *)video_raster[i];
  820.         UBYTE *p2 = (UBYTE *)ptr;
  821.         mmu_mark (video_raster[i], SCREENWIDTH * SCREENHEIGHT / 8 * video_depth,
  822.                   video_c_cache_mode, SysBase);
  823.         FreeVec (p2 - ptr[-1]);
  824.       } else
  825.         FreeRaster (video_raster[i], SCREENWIDTH, video_depth * SCREENHEIGHT);
  826.       video_raster[i] = NULL;
  827.     }
  828.     if (video_compare_buffer[i] != NULL) {
  829.       free (video_compare_buffer[i]);
  830.       video_compare_buffer[i] = NULL;
  831.     }
  832.   }
  833.   if (video_use_mmu && !video_is_directcgx) {
  834.     if (screens[0] != NULL)
  835.       mmu_mark (screens[0], (SCREENWIDTH * SCREENHEIGHT + 4096) & ~0xfff,
  836.                 video_f_cache_mode, SysBase);
  837.   }
  838.   if (CyberGfxBase == NULL) {
  839.     CloseLibrary (CyberGfxBase);
  840.     CyberGfxBase = NULL;
  841.   }
  842.   /* experimental c2p stuff */
  843.   if (c2p && !video_is_using_blitter) {
  844.     c2p8_deinit (c2p, SysBase);
  845.     c2p = NULL;
  846.   }
  847.   if (!timerclosed) {
  848.     if (!CheckIO((struct IORequest *)timerio)) {
  849.       AbortIO ((struct IORequest *)timerio);
  850.       WaitIO ((struct IORequest *)timerio);
  851.     }
  852.     CloseDevice ((struct IORequest *)timerio);
  853.     timerclosed = TRUE;
  854.     TimerBase = NULL;
  855.   }
  856.   if (timerio != NULL) {
  857.     DeleteExtIO ((struct IORequest *)timerio);
  858.     timerio = NULL;
  859.   }
  860.   if (timermp != NULL) {
  861.     DeletePort (timermp);
  862.     timermp = NULL;
  863.   }
  864. }
  865.  
  866. /**********************************************************************/
  867. // Takes full 8 bit values.
  868. void I_SetPalette (byte *palette)
  869. {
  870.   int i;
  871.   ULONG c, *p;
  872.   UBYTE *g;
  873.   static UBYTE gpalette[3*256];
  874.  
  875.   /* printf ("I_SetPalette()\n"); */
  876.   if (video_is_ehb_mode) {
  877.     g = gpalette;
  878.     for (i = 0; i < 256; i++) {
  879.       *g++ = gammatable[usegamma][*palette++];
  880.       *g++ = gammatable[usegamma][*palette++];
  881.       *g++ = gammatable[usegamma][*palette++];
  882.     }
  883.     video_colourtable[0] = (32 << 16) + 0;
  884.     median_cut (gpalette, &video_colourtable[1], video_xlate);
  885.     video_colourtable[33] = 0;
  886.   } else {
  887.     p = video_colourtable;
  888.     *p++ = (256 << 16) + 0;
  889.     for (i = 0; i < 256; i++) {
  890.       c = (ULONG)gammatable[usegamma][*palette++];
  891.       c += (c<<8);
  892.       c += (c<<16);
  893.       *p++ = c;
  894.       c = (ULONG)gammatable[usegamma][*palette++];
  895.       c += (c<<8);
  896.       c += (c<<16);
  897.       *p++ = c;
  898.       c = (ULONG)gammatable[usegamma][*palette++];
  899.       c += (c<<8);
  900.       c += (c<<16);
  901.       *p++ = c;
  902.     }
  903.     *p++ = 0;
  904.   }
  905.   if (video_is_ehb_mode)
  906.     if (video_is_using_blitter) {
  907.       video_palette_changed = 2;  /* double buffering */
  908.     } else
  909.       video_palette_changed = 3;  /* triple buffering */
  910.   else
  911.     video_palette_changed = 1;
  912. }
  913.  
  914. /**********************************************************************/
  915. void I_StartUpdate (void)
  916. {
  917.   UBYTE *base_address;
  918.  
  919.   if (video_is_directcgx) {
  920.     if (video_palette_changed != 0) {
  921.       LoadRGB32 (&video_screen->ViewPort, video_colourtable);
  922.       video_palette_changed = 0;
  923.     }
  924.     if (!video_bitmap_is_locked) {
  925.       start_timer ();
  926.       video_bitmap_handle = LockBitMapTags (video_screen->ViewPort.RasInfo->BitMap,
  927.                                             LBMI_BASEADDRESS, &base_address,
  928.                                             TAG_DONE);
  929.       lock_time += end_timer ();
  930.       video_bitmap_is_locked = TRUE;
  931. /*
  932.       video_which = 1 - video_which;
  933.       if (video_which != 0)
  934.         screens[0] = base_address + (SCREENWIDTH * video_oscan_height);
  935.       else
  936. */
  937.       screens[0] = base_address;
  938.     }
  939.   }
  940. }
  941.  
  942. /**********************************************************************/
  943. void I_UpdateNoBlit (void)
  944. {
  945. }
  946.  
  947. /**********************************************************************/
  948. void I_FinishUpdate (void)
  949. /* This needs optimising to copy just the parts that changed,
  950.    especially if the user has shrunk the playscreen. */
  951. {
  952.   total_frames++;
  953.  
  954.   if (video_is_directcgx) {
  955.     if (video_bitmap_is_locked) {
  956.       UnLockBitMap (video_bitmap_handle);
  957.       video_bitmap_is_locked = FALSE;
  958. /*
  959.       video_screen->ViewPort.RasInfo->RyOffset = video_which != 0 ?
  960.                                                          video_oscan_height : 0;
  961.       ScrollVPort (&video_screen->ViewPort);
  962. */
  963.     } else
  964.       I_Error ("I_FinishUpdate() called without calling I_StartUpdate() first");
  965.  
  966.     if (video_doing_fps)
  967.       video_do_fps (video_window->RPort);
  968.     return;
  969.   }
  970.  
  971.   if (video_is_native_mode) {
  972.     if (video_is_using_blitter) {
  973.       start_timer();
  974.       Wait (1 << video_sigbit1); /* wait for prev c2p() to finish pass 3 */
  975.       blit_time += end_timer();
  976.       if (video_blit_is_in_progress) {
  977.     start_timer();
  978.     Wait (SIGBREAKF_CTRL_F); /* wait for prev ChangeScreenBuffer() safe */
  979.     safe_time += end_timer();
  980.     video_blit_is_in_progress = FALSE;
  981.       }
  982.       video_which = 1 - video_which;  /* render to the hidden bitmap */
  983.       start_timer();
  984.       if (video_is_ehb_mode) {
  985.         c2p_6_020 (screens[0],
  986.                    video_bitmap[video_which].Planes,
  987.                    1 << video_sigbit1, 1 << video_sigbit2, 1 << video_sigbit3,
  988.                    SCREENWIDTH * SCREENHEIGHT, 0, video_xlate, video_fliptask);
  989.       } else {
  990.         if (cpu_type < 68030)
  991.           c2p_8_020 (screens[0],
  992.                      video_bitmap[video_which].Planes,
  993.                      1 << video_sigbit1, 1 << video_sigbit2, 1 << video_sigbit3,
  994.                      SCREENWIDTH * SCREENHEIGHT, 0, video_fliptask);
  995.         else
  996.           c2p1x1_cpu3blit1_queue (screens[0], video_raster[video_which]);
  997.       }
  998.       c2p_time += end_timer();
  999.       video_blit_is_in_progress = TRUE;
  1000.       if (video_palette_changed > 0) {
  1001.         video_palette_changed--; /* keep it set for 2 frames for dblbuffering */
  1002.       }
  1003.     } else {
  1004.       start_timer();
  1005.       if (video_is_ehb_mode) {
  1006.         c2p_6_040 (screens[0], video_raster[video_which],
  1007.                    video_compare_buffer[video_which], video_xlate,
  1008.                    (SCREENWIDTH * SCREENHEIGHT) >> 3,
  1009.                    video_palette_changed);
  1010.         if (video_palette_changed > 0) {
  1011.           if (video_palette_changed == 3)
  1012.             LoadRGB32 (&video_screen->ViewPort, video_colourtable);
  1013.           video_palette_changed--;
  1014.         }
  1015.       } else {
  1016.         if (c2p && scaledviewwidth >= SCREENWIDTH-64)
  1017.            c2p (screens[0], video_raster[video_which],
  1018.                 screens[0] + SCREENWIDTH * SCREENHEIGHT);
  1019.         else
  1020.           c2p_8_040 (screens[0], video_raster[video_which],
  1021.                      video_compare_buffer[video_which],
  1022.                    (SCREENWIDTH * SCREENHEIGHT) >> 3);
  1023.         if (video_palette_changed != 0) {
  1024.           LoadRGB32 (&video_screen->ViewPort, video_colourtable);
  1025.           video_palette_changed = 0;
  1026.         }
  1027.       }
  1028.       c2p_time += end_timer();
  1029.       if (video_doing_fps)
  1030.         video_do_fps (&video_rastport[video_which]);
  1031.       WaitPort (video_mp);
  1032.       while (GetMsg (video_mp))
  1033.     /* do nothing */ ;
  1034.       ChangeVPBitMap (&video_screen->ViewPort, &video_bitmap[video_which],
  1035.                       video_db);
  1036.       if (++video_which == 3)
  1037.         video_which = 0;
  1038.     }
  1039.   } else {  /* non-native ScreenMode */
  1040.     if (video_palette_changed != 0) {
  1041.       LoadRGB32 (&video_screen->ViewPort, video_colourtable);
  1042.       video_palette_changed = 0;
  1043.     }
  1044.     start_timer();
  1045.     WritePixelArray8 (video_window->RPort, 0, 0, SCREENWIDTH-1, SCREENHEIGHT-1,
  1046.                       screens[0], &video_temprp);
  1047.     wpa8_time += end_timer();
  1048.     if (video_doing_fps)
  1049.       video_do_fps (video_window->RPort);
  1050.   }
  1051. }
  1052.  
  1053. /**********************************************************************/
  1054. // Wait for vertical retrace or pause a bit.  Use when quit game.
  1055. void I_WaitVBL(int count)
  1056. {
  1057.   for ( ; count > 0; count--)
  1058.     WaitTOF();
  1059. }
  1060.  
  1061. /**********************************************************************/
  1062. void I_ReadScreen (byte* scr)
  1063. {
  1064. /*
  1065.   if (video_is_directcgx) {
  1066.     printf ("I_ReadScreen() %d %d\n", video_which, video_bitmap_is_locked);
  1067.     ReadPixelArray8 (&video_rastport[0], 0,
  1068.                      video_which != 0 ? 0 : video_oscan_height,
  1069.                      SCREENWIDTH-1, SCREENHEIGHT-1, scr, &video_temprp);
  1070.   } else
  1071. */
  1072. /*
  1073.   if (video_is_directcgx)
  1074.     if (video_which)
  1075.       memcpy (scr, screens[0] - SCREENWIDTH * video_oscan_height,
  1076.               SCREENWIDTH * SCREENHEIGHT);
  1077.     else
  1078.       memcpy (scr, screens[0] + SCREENWIDTH * video_oscan_height,
  1079.               SCREENWIDTH * SCREENHEIGHT);
  1080.   else
  1081. */
  1082.   memcpy (scr, screens[0], SCREENWIDTH * SCREENHEIGHT);
  1083. }
  1084.  
  1085. /**********************************************************************/
  1086. void I_BeginRead (void)
  1087. {
  1088. }
  1089.  
  1090. /**********************************************************************/
  1091. void I_EndRead (void)
  1092. {
  1093. }
  1094.  
  1095. /**********************************************************************/
  1096. void amiga_getevents (void)
  1097. {
  1098.   event_t event;
  1099.   ULONG class;
  1100.   UWORD code;
  1101.   WORD mousex, mousey;
  1102.   struct IntuiMessage *msg;
  1103.   static ULONG previous = 0;
  1104.   static int xlate[0x68] = {
  1105.     '`', '1', '2', '3', '4', '5', '6', '7',
  1106.     '8', '9', '0', KEY_MINUS, KEY_EQUALS, '\\', 0, '0',
  1107.     'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
  1108.     'o', 'p', KEY_F11, KEY_F12, 0, '0', '2', '3',
  1109.     'a', 's', 'd', 'f', 'g', 'h', 'j', 'k',
  1110.     'l', ';', '\'', KEY_ENTER, 0, '4', '5', '6',
  1111.     KEY_RSHIFT, 'z', 'x', 'c', 'v', 'b', 'n', 'm',
  1112.     ',', '.', '/', 0, '.', '7', '8', '9',
  1113.     ' ', KEY_BACKSPACE, KEY_TAB, KEY_ENTER, KEY_ENTER, KEY_ESCAPE, KEY_BACKSPACE,
  1114.     0, 0, 0, KEY_MINUS, 0, KEY_UPARROW, KEY_DOWNARROW, KEY_RIGHTARROW, KEY_LEFTARROW,
  1115.     KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8,
  1116.     KEY_F9, KEY_F10, '(', ')', '/', '*', KEY_EQUALS, KEY_PAUSE,
  1117.     KEY_RSHIFT, KEY_RSHIFT, 0, KEY_RCTRL, KEY_LALT, KEY_RALT, 0, KEY_RCTRL
  1118.   };
  1119.   static event_t joyevent = {0}, mouseevent = {0};
  1120.  
  1121.   if (video_window != NULL) {
  1122.     while ((msg = (struct IntuiMessage *)GetMsg (video_window->UserPort)) != NULL) {
  1123.       class = msg->Class;
  1124.       code = msg->Code;
  1125.       mousex = msg->MouseX;
  1126.       mousey = msg->MouseY;
  1127.       ReplyMsg ((struct Message *)msg);
  1128.       if (class == IDCMP_RAWKEY) {
  1129.         if ((code & 0x80) != 0) {
  1130.           code &= ~0x80;
  1131.       event.type = ev_keyup;
  1132.         } else {
  1133.           event.type = ev_keydown;
  1134.         }
  1135.         if (code < 0x68 && xlate[code] != 0) {
  1136.           event.data1 = xlate[code];
  1137.           D_PostEvent (&event);
  1138.         }
  1139.       } else if (class == IDCMP_MOUSEMOVE) {
  1140.         mouseevent.type = ev_mouse;
  1141.         mouseevent.data2 = (mousex << 3);
  1142.         mouseevent.data3 = -(mousey << 5);
  1143.         D_PostEvent (&mouseevent);
  1144.       } else if (class == IDCMP_MOUSEBUTTONS) {
  1145.         mouseevent.type = ev_mouse;
  1146.         switch (code) {
  1147.           case SELECTDOWN:
  1148.             mouseevent.data1 |= 1;
  1149.             break;
  1150.           case SELECTUP:
  1151.             mouseevent.data1 &= ~1;
  1152.             break;
  1153.           case MENUDOWN:
  1154.             mouseevent.data1 |= 2;
  1155.             break;
  1156.           case MENUUP:
  1157.             mouseevent.data1 &= ~2;
  1158.             break;
  1159.           case MIDDLEDOWN:
  1160.             mouseevent.data1 |= 4;
  1161.             break;
  1162.           case MIDDLEUP:
  1163.             mouseevent.data1 &= ~4;
  1164.             break;
  1165.           default:
  1166.             break;
  1167.         }
  1168.         D_PostEvent (&mouseevent);
  1169.       }
  1170.     }
  1171.   }
  1172.  
  1173.   if (gameport_is_open && gameport_io_in_progress) {
  1174.     while (GetMsg (gameport_mp) != NULL) {
  1175.       switch (gameport_ie.ie_Code) {
  1176.         case IECODE_LBUTTON:
  1177.           joyevent.data1 |= 1;
  1178.           break;
  1179.         case IECODE_LBUTTON | IECODE_UP_PREFIX:
  1180.           joyevent.data1 &= ~1;
  1181.           break;
  1182.         case IECODE_RBUTTON:
  1183.           joyevent.data1 |= 2;
  1184.           break;
  1185.         case IECODE_RBUTTON | IECODE_UP_PREFIX:
  1186.           joyevent.data1 &= ~2;
  1187.           break;
  1188.         case IECODE_MBUTTON:
  1189.           joyevent.data1 |= 4;
  1190.           break;
  1191.         case IECODE_MBUTTON | IECODE_UP_PREFIX:
  1192.           joyevent.data1 &= ~4;
  1193.           break;
  1194.         case IECODE_NOBUTTON:
  1195.           joyevent.data2 = gameport_ie.ie_X;
  1196.           joyevent.data3 = gameport_ie.ie_Y;
  1197.           break;
  1198.         default:
  1199.           break;
  1200.       }
  1201.       joyevent.type = ev_joystick;
  1202.       D_PostEvent (&joyevent);
  1203.       gameport_io->io_Command = GPD_READEVENT;
  1204.       gameport_io->io_Length = sizeof (struct InputEvent);
  1205.       gameport_io->io_Data = &gameport_ie;
  1206.       SendIO ((struct IORequest *)gameport_io);
  1207.     }
  1208.   }
  1209.  
  1210.   /* CD32 joypad handler code supplied by Gabry (ggreco@iol.it) */
  1211.  
  1212.   if (LowLevelBase != NULL) {
  1213.     event_t joyevent;
  1214.     ULONG joypos = ReadJoyPort (1);
  1215.  
  1216.     if (previous == joypos)
  1217.       return;
  1218.  
  1219.     joyevent.type = ev_joystick;
  1220.     joyevent.data1 = joyevent.data2 = joyevent.data3 = 0;
  1221.  
  1222.     if (joypos & JPF_BUTTON_RED)
  1223.       joyevent.data1 |= 1;
  1224.     else
  1225.       joyevent.data1 &= ~1;
  1226.  
  1227.     if (joypos & JP_DIRECTION_MASK) {
  1228.       if (joypos & JPF_JOY_LEFT) {
  1229.         joyevent.data2 = -1;
  1230.       } else if (joypos & JPF_JOY_RIGHT) {
  1231.         joyevent.data2 = 1;
  1232.       }
  1233.       if (joypos & JPF_JOY_UP) {
  1234.         joyevent.data3 = -1;
  1235.       } else if (joypos & JPF_JOY_DOWN) {
  1236.         joyevent.data3 = 1;
  1237.       }
  1238.     }
  1239.  
  1240.     if (joypos & JP_TYPE_GAMECTLR) {
  1241.       event_t event;
  1242.  
  1243.       // Play/Pause = ESC (Menu)
  1244.       if (joypos & JPF_BUTTON_PLAY && !(previous & JPF_BUTTON_PLAY)) {
  1245.         event.type = ev_keydown;
  1246.         event.data1 = KEY_ESCAPE;
  1247.         D_PostEvent (&event);
  1248.       } else if (previous & JPF_BUTTON_PLAY) {
  1249.         event.type = ev_keyup;
  1250.         event.data1 = KEY_ESCAPE;
  1251.         D_PostEvent (&event);
  1252.       }
  1253.  
  1254.       // YELLOW = SHIFT (button 2) (Run)
  1255.       if (joypos & JPF_BUTTON_YELLOW)
  1256.         joyevent.data1 |= 4;
  1257.       else
  1258.         joyevent.data1 &= ~4;
  1259.  
  1260.       // BLUE = SPACE (button 3) (Open/Operate)
  1261.  
  1262.       if (joypos & JPF_BUTTON_BLUE)
  1263.         joyevent.data1 |= 8;
  1264.       else
  1265.         joyevent.data1 &= ~8;
  1266.  
  1267.       // GREEN = RETURN (show msg)
  1268.  
  1269.       if (joypos & JPF_BUTTON_GREEN && !(previous&JPF_BUTTON_GREEN)) {
  1270.         event.type = ev_keydown;
  1271.         event.data1 = 13;
  1272.         D_PostEvent (&event);
  1273.       } else if (previous & JPF_BUTTON_GREEN) {
  1274.         event.type = ev_keyup;
  1275.         event.data1 = 13;
  1276.         D_PostEvent (&event);
  1277.       }
  1278.  
  1279.       // FORWARD & REVERSE - ALT (Button1) Strafe left/right
  1280.  
  1281.       if (joypos & JPF_BUTTON_FORWARD) {
  1282.         joyevent.data1 |= 2;
  1283.         joyevent.data2 = 1;
  1284.       } else if (joypos & JPF_BUTTON_REVERSE) {
  1285.         joyevent.data1 |=2;
  1286.         joyevent.data2=-1;
  1287.       } else
  1288.         joyevent.data1 &= ~2;
  1289.     }
  1290.  
  1291.     D_PostEvent (&joyevent);
  1292.  
  1293.     previous = joypos;
  1294.   }
  1295.  
  1296. }
  1297.  
  1298. /**********************************************************************/
  1299. static void calc_time (ULONG time, char *msg)
  1300. {
  1301.   printf ("Total %s = %u us  (%u us/frame)\n", msg,
  1302.           (ULONG)(1000000.0 * ((double)time) / ((double)eclocks_per_second)),
  1303.           (ULONG)(1000000.0 * ((double)time) / ((double)eclocks_per_second) /
  1304.                   ((double)total_frames)));
  1305. }
  1306.  
  1307. /**********************************************************************/
  1308. void _STDvideo_cleanup (void)
  1309. {
  1310.   I_ShutdownGraphics ();
  1311.   if (video_smr != NULL) {
  1312.     FreeAslRequest (video_smr);
  1313.     video_smr = NULL;
  1314.   }
  1315.   /* printf ("EClocks per second = %d\n", eclocks_per_second); */
  1316.   if (total_frames > 0) {
  1317.     printf ("Total number of frames = %u\n", total_frames);
  1318.     calc_time (blit_time, "blit wait time ");
  1319.     calc_time (safe_time, "safe wait time ");
  1320.     calc_time (c2p_time,  "C2P time       ");
  1321.     calc_time (wpa8_time, "WPA8 time      ");
  1322.     calc_time (lock_time, "LockBitMap time");
  1323.   }
  1324. }
  1325.  
  1326. /**********************************************************************/
  1327.